package com.gitee.l0km.jsonvisitor.fastjson;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.net.URI;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.file.Files;
import java.nio.file.Path;

import com.alibaba.fastjson.parser.JSONLexer;
import com.alibaba.fastjson.parser.JSONReaderScanner;
import com.alibaba.fastjson.parser.JSONScanner;

public class Fastjsons {
	/**
	 * 返回buffer中所有字节(position~limit),不改变buffer状态
	 * @param buffer
	 * @return buffer 为 null 时返回 null 
	 * @throws IOException 
	 */
	private static final byte[] getBytesInChannel(ReadableByteChannel channel) throws IOException{
		if(null == channel){
			return null;
		}
		AutoExpandingBuffer autoBuffer = new AutoExpandingBuffer();
		ByteBuffer buffer = ByteBuffer.allocate(1024);
		while(channel.read(buffer)>0) {
			buffer.flip();
			autoBuffer.write(buffer);
			buffer.clear();
		}
		return autoBuffer.copy();
	}
	/**
	 * 返回buffer中所有字节(position~limit),不改变buffer状态
	 * @param buffer
	 * @return buffer 为 null 时返回 null 
	 */
	private static final byte[] getBytesInBuffer(ByteBuffer buffer){
		if(null == buffer){
			return null;
		}
		int pos = buffer.position();
		try{
			byte[] bytes = new byte[buffer.remaining()];
			buffer.get(bytes);
			return bytes;
		}finally{
			buffer.position(pos);
		}
	}
	/**
	 * 从{@link InputStream}读取字节数组<br>
	 * 当{@code in}为{@link FileInputStream}时，调用{@link #readBytes(FileInputStream)}(NIO方式)读取<br>
	 *  结束时会关闭{@link InputStream}
	 * @param in 为{@code null}返回{@code null}
	 * @return 读取的字节数组
	 * @throws IOException
	 * @throws IllegalArgumentException {@code in}为{@code null}
	 */
	public static final byte[] readBytes(InputStream in) throws IOException, IllegalArgumentException {
		if(null == in){
			return null;
		}
		try {
			int buffSize = Math.max(in.available(), 1024*8);
			byte[] temp = new byte[buffSize];
			ByteArrayOutputStream out = new ByteArrayOutputStream(buffSize);
			int size = 0;
			while ((size = in.read(temp)) != -1) {
				out.write(temp, 0, size);
			}
			return  out.toByteArray();
		} finally {
			in.close();
		}
	}
	/**
	 * 返回buffer中所有char(position~limit),不改变buffer状态
	 * 
	 * @param buffer
	 * @return buffer 为 null 时返回 null
	 */
	private static final char[] getCharsInBuffer(CharBuffer buffer) {
		if (null == buffer) {
			return null;
		}
		int pos = buffer.position();
		try {
			char[] bytes = new char[buffer.remaining()];
			buffer.get(bytes);
			return bytes;
		} finally {
			buffer.position(pos);
		}
	}
	/**
	 * 返回buffer中所有char(position~limit),不改变buffer状态
	 * 
	 * @param reader
	 * @return buffer 为 null 时返回 null
	 * @throws IOException 
	 */
	private static final String getStringInReader(Reader reader) throws IOException {
		if (null == reader) {
			return null;
		}
		StringBuffer buffer = new StringBuffer();
		char[] buf = new char[1024];
		int size = 0;
		while ((size = reader.read(buf)) >0) {
			buffer.append(buffer,0,size);
		}
		return buffer.toString();
	}

	/**
	 * 将数据源转为{@link JSONLexer}<br>
	 * 支持的类型：<br>
	 * {@link JSONLexer},{@link Path},{@link File},{@link InputStream},{@link ReadableByteChannel},
	 * {@link URL},{@link URI},
	 * {@link Reader},{@link String},{@link ByteBuffer},{@link CharBuffer},
	 * byte[],char[]<br>
	 * 否则抛出异常{@link IllegalArgumentException}
	 * 
	 * @param src
	 * @throws IllegalArgumentException 不支持的数据源类型
	 */
	public static String asInputString(Object src) throws IllegalArgumentException {
		try {
			if( src instanceof String) {
				return (String)src;
			}else if (src instanceof Path) {
				try (ReadableByteChannel channel = Files.newByteChannel(((Path) src))) {
					return asInputString(channel);
				}
			} else if (src instanceof File) {
				try (FileInputStream is = new FileInputStream(((File) src))) {
					return asInputString(is);
				}
			} else if (src instanceof InputStream) {
				return asInputString(readBytes((InputStream) src));
			} else if (src instanceof ReadableByteChannel) {
				return asInputString(getBytesInChannel((ReadableByteChannel) src));
			} else if (src instanceof URL) {
				try (InputStream is = ((URL) src).openStream()) {
					return asInputString(is);
				}
			} else if (src instanceof URI) {
				return asInputString(((URI) src).toURL());
			} else if (src instanceof Reader) {
				return asInputString(getStringInReader((Reader) src));
			} else if (src instanceof ByteBuffer) {
				return asInputString(getBytesInBuffer((ByteBuffer) src));
			} else if (src instanceof CharBuffer) {
				return asInputString(getCharsInBuffer((CharBuffer) src));
			} else if (src instanceof byte[]) {
				return asInputString(new String((byte[]) src));
			} else if (src instanceof char[]) {
				return asInputString(new String((char[]) src));
			} else if (null != src) {
				throw new IllegalArgumentException("UNSUPPORTED Source Type:" + src.getClass().getName());
			}
			return null;
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
	/**
	 * 将数据源转为{@link JSONLexer}<br>
	 * 支持的类型：<br>
	 * {@link JSONLexer},{@link Path},{@link File},{@link InputStream},{@link ReadableByteChannel},
	 * {@link URL},{@link URI},
	 * {@link Reader},{@link String},{@link ByteBuffer},{@link CharBuffer},
	 * byte[],char[]<br>
	 * 否则抛出异常{@link IllegalArgumentException}
	 * 
	 * @param src
	 * @throws IllegalArgumentException 不支持的数据源类型
	 */
	public static JSONLexer createJSONLexer(Object src) throws IllegalArgumentException {
		try {
			if( src instanceof JSONLexer) {
				return (JSONLexer)src;
			}else if (src instanceof Path) {
				try (ReadableByteChannel channel = Files.newByteChannel(((Path) src))) {
					return createJSONLexer(channel);
				}
			} else if (src instanceof File) {
				try (FileInputStream is = new FileInputStream(((File) src))) {
					return createJSONLexer(is);
				}
			} else if (src instanceof InputStream) {
				return createJSONLexer(readBytes((InputStream) src));
			} else if (src instanceof ReadableByteChannel) {
				return createJSONLexer(getBytesInChannel((ReadableByteChannel) src));
			} else if (src instanceof URL) {
				try (InputStream is = ((URL) src).openStream()) {
					return createJSONLexer(is);
				}
			} else if (src instanceof URI) {
				return createJSONLexer(((URI) src).toURL());
			} else if (src instanceof Reader) {
				return new JSONReaderScanner((Reader) src);
			} else if (src instanceof String) {
				return new JSONScanner((String) src);
			} else if (src instanceof ByteBuffer) {
				return createJSONLexer(getBytesInBuffer((ByteBuffer) src));
			} else if (src instanceof CharBuffer) {
				return createJSONLexer(getCharsInBuffer((CharBuffer) src));
			} else if (src instanceof byte[]) {
				return createJSONLexer(new String((byte[]) src));
			} else if (src instanceof char[]) {
				return createJSONLexer(new String((char[]) src));
			} else if (null != src) {
				throw new IllegalArgumentException("UNSUPPORTED Source Type:" + src.getClass().getName());
			}
			return null;
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
}
